using System.Collections.Generic;
using System.Linq;
using SymbolIntegration.core.Expressions;

namespace SymbolIntegration.core.Helpers
{
    public class Polinom
    {
        private Dictionary<int, Expression> m_ConstantsNearPower = new  Dictionary<int, Expression>();
        private readonly string m_Variable;

        public Polinom(string variable)
        {
            m_ConstantsNearPower[0] = new ConstantExpression(0);
            m_Variable = variable;
        }

        public int GetMaxPower()
        {
            return m_ConstantsNearPower.Max(pair => pair.Key);
        }

        public Expression GetConstantAt(int power)
        {
            Expression result = m_ConstantsNearPower.ContainsKey(power) ? m_ConstantsNearPower[power] : new ConstantExpression(0);
            return result;
        }

        public Expression Integrate()
        {
            Expression result = new ConstantExpression(0);
            foreach (var expression in m_ConstantsNearPower)
            {
                result = result +
                         (new VariableExpression(m_Variable) ^ new ConstantExpression(expression.Key + 1))
                         * expression.Value / new ConstantExpression(expression.Key + 1);
            }
            return result;
        }

        public void SetConstantAt(int position, Expression expression)
        {
            m_ConstantsNearPower[position] = expression;
        }

        public void Mul(Polinom mulPolinom)
        {
            var newDictionary = new Dictionary<int, Expression>();
            foreach (var pair in mulPolinom.m_ConstantsNearPower)
            {
                foreach (var selfPair in m_ConstantsNearPower)
                {
                    int resultKey = selfPair.Key + pair.Key;
                    var resultConstant = (selfPair.Value*pair.Value).Normalize();
                    if (newDictionary.ContainsKey(resultKey))
                    {
                        newDictionary[resultKey] = (newDictionary[resultKey] + resultConstant).Normalize();
                    }
                    else
                    {
                        newDictionary[resultKey] = resultConstant;
                    }
                }
            }
            m_ConstantsNearPower = newDictionary;
        }

        public void Add(Polinom addPolinom)
        {
            foreach (var pair in addPolinom.m_ConstantsNearPower)
            {
                if (m_ConstantsNearPower.ContainsKey(pair.Key))
                {
                    m_ConstantsNearPower[pair.Key] = (m_ConstantsNearPower[pair.Key] + pair.Value).Normalize();
                }
                else
                {
                    m_ConstantsNearPower[pair.Key] = pair.Value;
                }
            }
        }
    }
}